/*
AUTHOR:Klaoye
DATE:8/24/2020
LICENSE:MIT
*/
#include<reg51.h>
#include<math.h>
#define     COF       120000L // 晶振频率Crystal oscillator frequency
#define			KEY							P0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    //键盘Keyboard
typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

sbit Buzzer=P2^3;//接蜂鸣器引脚Connected to buzzer pin
sbit p31 = P3^1;//接独立按钮

//音调频率pitch frequency
const u16 note[4][8]=
{
	{0,262,294,330,349,392,440,494},
	{0,523,578,659,698,784,880,988},
	{0,1046,1175,1318,1397,1568,1760,1976},
	{0,2093,2349,2637,2794,3135,3950,4186}
};

void buzzer(u16 f,u16 time_ms);
void delay(u16 t_ms);
short keyPress();

void main()
{
	short i,s;
	p31=1;
	Buzzer = 1;
	while(1)
	{
		i = keyPress();
		p31 == 0 ? (s = 2):(s = 0);//移调
		if(i>=0)
		{
			buzzer(note[i/8+s][i%8],50);
			//i=0;
		}
		p31=1;
	}
}

short keyPress()//按键检测Keyboard detection module
{
	u8 col/*行*/,row;/*列*/
	KEY = 0xf0;
	if(KEY != 0xf0)
	{
		delay(5);//程序防抖Program anti shake
		if(KEY != 0xf0)
		{
			switch (KEY)//扫描行位Scanning line position
			{
				case 0x70: row = 0;break;
				case 0xb0: row = 1;break;
				case 0xd0: row = 2;break;
				case 0xe0: row = 3;break;
				default:break;
			}
			KEY = 0x0f;
			switch (KEY)//扫描列位Scanning column
			{
				case 0x07: col = 0;break;
				case 0x0b: col = 1;break;
				case 0x0d: col = 2;break;
				case 0x0e: col = 3;break;
				default:break;
			}
			return col * 4 + row;
		}else{
			return -1;
		}
	}else{
		return -1;
	}
	
}

void delay(u16 t_ms)//延时
{
	u16 min;
	do{
		for(min= COF / 1200;min>0;min--);
	}while(t_ms--);
}

void buzzer(u16 f,u16 time_ms)//发声，f音调，time_ms维持时间Voice, f tone, time_ Ms duration
{
	u16 time = (COF / 1200)*time_ms;
	u16 C= COF/(8*f);
	u16 x=0;
	P1 = 0xff ^ (C % 0xff);//8bit亮灯（可选）8bit on LED(optional)
	for(;time>0;time--)
	{
		if(x>C){
			Buzzer=0;
			x=0;
		}
		else
		{
			x++;
			Buzzer=1;
		}
	}
	Buzzer=1;
	P1 = 0xff;
}